'''
copyright: Copyright (C) 2015-2024, Wazuh Inc.

           Created by Wazuh, Inc. <info@wazuh.com>.

           This program is free software; you can redistribute it and/or modify it under the terms of GPLv2

type: integration

brief: These tests will check if the `min_full_scan_interval` option of the Vulnerability Detector module
       is working correctly. This option is located in its corresponding section of the `ossec.conf` file
       and allows to define the minimum time before performing a full scan even if the feed was updated. The extended
       behavior also checks that the full scan is performed as expected.

components:
    - vulnerability_detector

suite: general_settings

targets:
    - manager

daemons:
    - wazuh-modulesd

os_platform:
    - linux

os_version:
    - Arch Linux
    - Amazon Linux 2
    - Amazon Linux 1
    - CentOS 8
    - CentOS 7
    - Debian Buster
    - Red Hat 8
    - Ubuntu Focal
    - Ubuntu Bionic

references:
    - https://documentation.wazuh.com/current/user-manual/capabilities/vulnerability-detection/index.html
    - https://documentation.wazuh.com/current/user-manual/reference/ossec-conf/vuln-detector.html#min_full_scan_interval
    - https://github.com/wazuh/wazuh/issues/7749
    - https://github.com/wazuh/wazuh/issues/8727

tags:
    - settings
    - general_settings
'''
import pytest
from pathlib import Path

from wazuh_testing.constants.daemons import ANALYSISD_DAEMON, MODULES_DAEMON, SYSCHECK_DAEMON
from wazuh_testing.constants.paths.logs import WAZUH_LOG_PATH
from wazuh_testing.utils.callbacks import generate_callback
from wazuh_testing.utils.time import time_to_seconds
from wazuh_testing.tools.monitors.file_monitor import FileMonitor
from wazuh_testing.utils.db_queries import agent_db, cve_db
from wazuh_testing.utils.configuration import (get_test_cases_data, load_configuration_template,
                                               update_configuration_template)
from wazuh_testing.modules.modulesd.vulnerability_detector import patterns as cb
from wazuh_testing.modules.modulesd.configuration import MODULESD_DEBUG
from wazuh_testing.modules.monitord.configuration import MONITORD_ROTATE_LOG
from test_vulnerability_detector import utils as evm
from . import (TEST_CASES_PATH, CONFIGURATIONS_PATH, custom_rhel_oval_feed_path, custom_rhel_json_feed_path,
               custom_nvd_json_feed_path)


pytest.skip("The tests will be deprecated, they test the old Vulnerability Detector.", allow_module_level=True)

# Variables
local_internal_options = {MODULESD_DEBUG: '2', MONITORD_ROTATE_LOG: '0'}
daemons_handler_configuration = {'daemons': [ANALYSISD_DAEMON, MODULES_DAEMON, SYSCHECK_DAEMON]}
pytestmark = [pytest.mark.server]

# Configuration and cases data
configurations_path = Path(CONFIGURATIONS_PATH, 'configuration_min_full_scan_interval.yaml')
test_cases_path = Path(TEST_CASES_PATH, 'cases_min_full_scan_interval.yaml')

# Test configurations
configuration_parameters, configuration_metadata, test_case_ids = get_test_cases_data(test_cases_path)
configurations = load_configuration_template(configurations_path, configuration_parameters,
                                             configuration_metadata)
systems = [metadata['system'] for metadata in configuration_metadata]

# Set offline custom feeds configuration
to_modify = ['RHEL_FEED_PATH', 'custom_rhel_json_feed_path', 'custom_nvd_json_feed_path']
new_values = [custom_rhel_oval_feed_path, custom_rhel_json_feed_path, custom_nvd_json_feed_path]
configurations = update_configuration_template(configurations, to_modify, new_values)


@pytest.mark.tier(level=0)
@pytest.mark.parametrize('test_configuration, test_metadata, agent_system',
                         zip(configurations, configuration_metadata, systems), ids=test_case_ids)
def test_min_full_scan_interval(test_configuration, test_metadata, agent_system, set_wazuh_configuration,
                                configure_local_internal_options, truncate_monitored_files, clean_cve_tables,
                                prepare_full_scan_environment, daemons_handler):
    '''
    description: Check that the full scan is started after passing the min_full_scan_interval time.

    test_phases:
        - setup:
            - Set a custom Wazuh configuration.
            - Configure custom local_internal_options.
            - Truncate wazuh logs.
            - Mock an agent with packages.
            - Update sync info a force the full scan.
            - Restart wazuh-modulesd daemon to apply configuration changes.
        - test:
            - Check the full scan event log
            - Clean NVD tables and import again the feed (simulate NVD feed update to force full scan)
            - Check again the full scan event log.
        - teardown:
            - Truncate wazuh logs.
            - Restore initial configuration, both ossec.conf and local_internal_options.conf.

    wazuh_min_version: 4.3.0

    tier: 0

    parameters:
        - test_configuration:
            type: dict
            brief: Configuration loaded from `configuration_template`.
        - test_metadata:
            type: dict
            brief: Test case metadata.
        - agent_system:
             type: str
             brief: System to set to the mocked agent.
        - set_wazuh_configuration:
            type: fixture
            brief: Set wazuh configuration.
        - configure_local_internal_options:
            type: fixture
            brief: Set local_internal_options configuration.
        - truncate_monitored_files:
            type: fixture
            brief: Truncate all the log files and json alerts files before and after the test execution.
        - clean_cve_tables:
             type: fixture
             brief: Clean all the CVE tables before and after running the test.
         - prepare_full_scan_environment:
             type: fixture
             brief: Setup the initial test state.
         - daemons_handler:
            type: fixture
            brief: Restart wazuh-modulesd daemon before starting a test, and stop it after finishing.

    assertions:
        - Verify that the full scan starts.
        - Verify that the full scan ends.

    input_description: The values specified in `data/test_cases`.

    expected_output:
        - f"A full scan will be run on agent '001'"
        - f"Finished vulnerability assessment for agent '001'"
    '''
    agent_id = prepare_full_scan_environment
    log_monitor = FileMonitor(WAZUH_LOG_PATH)

    event_timeout = time_to_seconds(test_metadata['min_full_scan_interval_value']) + 40

    # Wait for full scan event log
    log_present = evm.check_full_scan_start(agent_id, timeout=event_timeout)
    assert log_present is not None, f"No Full scan start log found."

    # Wait for full scan event log completion
    log_monitor.start(callback=generate_callback(regex=cb.FINISHED_VUNERABILITY_ASSESMENT,
                                                 replacement={"agent_id": agent_id}))
    assert log_monitor.callback_result is not None, f"Expected '{cb.FINISHED_VUNERABILITY_ASSESMENT}' event not found."

    # Clean NVD tables to force a full scan again after updating the NVD feed and passed the min_full_scan_interval
    cve_db.clean_nvd_tables()

    # Check again the full scan event
    log_present = evm.check_full_scan_start(agent_id, timeout=event_timeout)
    assert log_present is not None, f"No Full scan start log found."
